package com.vf.cloud.server.dispatch.util;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.JsonKit;
import com.jfinal.plugin.activerecord.Db;
import com.vf.cloud.pass.common.domain.biz.Terminal;
import com.vf.cloud.pass.common.domain.biz.TerminalGpu;
import com.vf.cloud.pass.common.factory.GPUFactory;
import com.vf.cloud.pass.common.vo.Gpu;
import com.vf.cloud.pass.common.vo.Local;
import com.vf.cloud.pass.common.vo.Streamer;
import com.vf.cloud.pass.common.vo.SysInfo;
import com.vf.cloud.server.dispatch.pool.DispatchPool;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

public class DispatchUtil {

	public static void disconnected(String channelId) {
		DispatchPool.removeNode(channelId);

	}

	public static void sendPing(ChannelHandlerContext ctx, long time) {
		Map<String, Object> clientConfig = new HashMap<String, Object>();
		clientConfig.put("type", "pong");
		clientConfig.put("time", time);
		send(ctx, JsonKit.toJson(clientConfig));
	}

	public static void sendPingForNode(ChannelHandlerContext ctx, long time) {
		Map<String, Object> clientConfig = new HashMap<String, Object>();
		clientConfig.put("type", "ping");
		clientConfig.put("time", time);
		send(ctx, JsonKit.toJson(clientConfig));
	}

	public static void sendSuccess(ChannelHandlerContext ctx, long time) {
		Map<String, Object> success = new HashMap<String, Object>();
		success.put("type", "event");

		Map<String, Object> data = new HashMap<String, Object>();
		data.put("func_name", "OnSuccess");
		data.put("time", time);
		success.put("data", data);
		send(ctx, JsonKit.toJson(success));
	}

	public static void sendFail(ChannelHandlerContext ctx, long time, String message) {
		Map<String, Object> failed = new HashMap<String, Object>();
		failed.put("type", "event");
		Map<String, Object> data = new HashMap<String, Object>();
		data.put("func_name", "OnFailed");
		data.put("time", time);
		data.put("message", message);
		failed.put("data", data);
		send(ctx, JsonKit.toJson(failed));
	}

	public static void send(ChannelHandlerContext ctx, String json) {
		if (ctx != null) {
			ctx.channel().writeAndFlush(new TextWebSocketFrame(json)).addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					if (future.isSuccess()) {
					} else {
					}
				}
			});
		}
	}

	public static void send(ChannelHandlerContext ctx, String json, long time) {
		if (ctx != null) {
			ctx.channel().writeAndFlush(new TextWebSocketFrame(json)).addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					if (future.isSuccess()) {
						sendSuccess(ctx, time);
					} else {
					}
				}
			});
		}
	}


	/**
	 * 处理配置
	 * 
	 * @param ctx
	 * @param rawMsg
	 */
	public static void handleConfig(ChannelHandlerContext ctx, JSONObject rawMsg) {
		Local local = JSONObject.parseObject(rawMsg.getString("data"), Local.class);
		if (local != null) {
			Terminal terminal = DispatchPool.getNodeByChannelId(ctx.channel().id().asLongText());
			if (terminal != null) {
				terminal.setIp(local.getIp());
				terminal.setPort("8881");
				terminal.setProjectPath(local.getProjectPath());
				if (terminal.update()) {
					sendSuccess(ctx, rawMsg.getLong("time"));
				} else {
					sendFail(ctx, rawMsg.getLong("time"), "同步节点本地配置失败.");
				}
			} else {
				sendFail(ctx, rawMsg.getLong("time"), "节点已经离线.");
			}
		} else {
			sendFail(ctx, rawMsg.getLong("time"), "节点配置信息空.");
		}
	}


	public static void handleGPUS(ChannelHandlerContext ctx, JSONObject rawMsg) {
		Terminal terminal = DispatchPool.getNodeByChannelId(ctx.channel().id().asLongText());
		if(terminal!=null) {
			List<Gpu> list = JSONObject.parseArray(rawMsg.getString("data"), Gpu.class);
			if (list != null && list.size() > 0) {
				StringBuffer sb=new StringBuffer();
				for (Gpu gpu : list) {
					TerminalGpu terminalGpu = TerminalGpu.dao.findById(gpu.getUuid());
					if (terminalGpu == null) {
						terminalGpu = new TerminalGpu();
						terminalGpu.setId(gpu.getUuid());
						terminalGpu.setGpuIndex(gpu.getIndex());
						terminalGpu.setGpuUsed(0);
						terminalGpu.setTerminalId(gpu.getMac());
						terminalGpu.setGpuName(gpu.getName());
						terminalGpu.setGpuStatus("1");
						terminalGpu.setGpuMemory(gpu.getMemoryTotal());
						terminalGpu.setGpuUtil(gpu.getGpuUtil());
						terminalGpu.setMemoryUtil(gpu.getMemoryUtil());
						terminalGpu.setDecoderUtil(gpu.getDecoderUtil());
						terminalGpu.setEncoderUtil(gpu.getEncoderUtil());
						terminalGpu.save();
					} else {
						terminalGpu.setGpuStatus("1");
						terminalGpu.update();
					}
					sb.append("'").append(gpu.getUuid()).append("'").append(",");
				}
				Db.delete("delete from "+TerminalGpu.TABLE_NAME+" where terminal_id=? and id not in("+sb.substring(0, sb.length()-1)+") ",terminal.getId());
			} else {
				Db.update("update "+TerminalGpu.TABLE_NAME+" set gpu_status='0' where terminal_id=?",terminal.getId());
			}
		}
		//池告知变换
	}


	/**
	 * 在线的流
	 * @param ctx
	 * @param rawMsg
	 */
	public static void handleStreamers(ChannelHandlerContext ctx, JSONObject rawMsg) {
		Terminal terminal = DispatchPool.getNodeByChannelId(ctx.channel().id().asLongText());
		if(terminal!=null) {
			List<Streamer> list = JSONObject.parseArray(rawMsg.getString("data"), Streamer.class);
			if (list != null && list.size() > 0) {
				for (Streamer s : list) {
					GPUFactory.getInstance().use(String.format("%s|%s|%s", s.getMac(),s.getIndex(),s.getBlock()),s.getSid());
				}
			}
			GPUFactory.getInstance().init(terminal.getId());
		}
	}

	/**
	 * 流上线
	 * @param ctx
	 * @param rawMsg
	 */
	public static void onStreamerConnected(ChannelHandlerContext ctx, JSONObject rawMsg) {
		
		Streamer streamer = JSONObject.parseObject(rawMsg.getString("data"), Streamer.class);
		if(streamer!=null) {
			GPUFactory.getInstance().onStreamerConnected(String.format("%s|%s|%s", streamer.getMac(),streamer.getIndex(),streamer.getBlock()));
		}
	}

	/**
	 * 流关闭
	 * @param ctx
	 * @param rawMsg
	 */
	public static void onStreamerDisconnected(ChannelHandlerContext ctx, JSONObject rawMsg) {
		Streamer streamer = JSONObject.parseObject(rawMsg.getString("data"), Streamer.class);
		if(streamer!=null) {
			GPUFactory.getInstance().onStreamerDisconnected(String.format("%s|%s|%s", streamer.getMac(),streamer.getIndex(),streamer.getBlock()));
		}
	}

	/**
	 * 渲染主机监控
	 * @param ctx
	 * @param rawMsg
	 */
	public static void onRenderingMonitor(ChannelHandlerContext ctx, JSONObject rawMsg) {
		SysInfo sysInfo = JSONObject.parseObject(rawMsg.getString("data"), SysInfo.class);
		if (sysInfo != null) {
			Terminal terminal = DispatchPool.getNodeByChannelId(ctx.channel().id().asLongText());
			if (terminal != null) {
				terminal.setOs(sysInfo.getOsName());
				terminal.setGpuMemoryTotal(sysInfo.getGpuMemoryTotal());
				terminal.setGpuMemoryUsed(sysInfo.getGpuMemoryUsed());
				terminal.setGpuNum(sysInfo.getGpuNum());
				terminal.setGpuModel(sysInfo.getGpuModel());
				terminal.setMemoryTotal(sysInfo.getMemoryTotal());
				terminal.setMemoryUsed(sysInfo.getMemoryUsed());
				terminal.setMemoryUsedPercentage(sysInfo.getMemoryUsedPercentage());
				terminal.setGpuMemoryUsedPercentage(sysInfo.getGpuMemoryUsedPercentage());
				if (terminal.update()) {
					sendSuccess(ctx, rawMsg.getLong("time"));
				} else {
					sendFail(ctx, rawMsg.getLong("time"), "同节点运行情况失败.");
				}
			} else {
				sendFail(ctx, rawMsg.getLong("time"), "节点已经离线.");
			}
		}
	}




}
